package sum_of_points;
import java.util.Scanner;
import java.io.FileReader;

public class Sum_of_points 
{
    public static void main(String[] args) 
    {
        try
        {
            Scanner s = new Scanner(new FileReader("res.txt"));
            String st = new String(); //st - следующее слово в файле
            List head = new List(); //head - первый элемент списка
            List zero = new List();
            List l = new List();
            List down = new List();
            List up = new List();
            down = up = head = l;
            int ll = 0; //ll - длина списка
            //Создаем первый элемент
            if(s.hasNext())
            {
                l.name = s.next();
                l.points = s.nextInt();
                ll++;
            }
            while (s.hasNext())
            {
                if(!s.hasNextInt())     st = s.next();
                //Если несколько подряд идущих одинаковых имен
                if(s.hasNext()&&l.name.equals(st))
                    while(l.name.equals(st))
                    {
                        l.points += s.nextInt();
                        if(s.hasNext())     st = s.next();
                        else    break;
                    }
                //Выполняется 1 из 3: если след. имя (st) больше (по алфавиту) последнего
                else if(l.name.compareTo(st)<0)
                {
                    l.next = new List();
                    l = l.next;
                    l.name = st;
                    l.points = s.nextInt();
                    ll++;
                }
                //если след. имя меньше первого
                else if(head.name.compareTo(st)>0)
                {
                    zero.next = new List();
                    zero.next.name = st;
                    zero.next.points = s.nextInt();
                    zero.next.next = head;
                    head = zero.next;
                    ll++;
                }
                //если имя лежит между именами списка/совпадает с именем из списка
                else 
                {
                    //цикл - реализация бинарного поиска
                    down = up = head;
                    for(int i=1; !down.next.equals(up); i++)
                    {
                        up = down.plus(ll/(i*2)+1); //plus - находит элемент списка с указанным номером
                        if(down.name.equals(st)||up.name.equals(st))    break;
                        if(up.name.compareTo(st)<0)     down = up;
                    }
                    //в итоге получаем 2 элемента такие, что
                    //либо имя совпадает с 1 из них,
                    if(down.name.equals(st))   down.points += s.nextInt();
                    else if(up.name.equals(st))   up.points += s.nextInt();
                    //либо след. слово либо нужно вставить между ними,
                    else if(down.next.equals(up))
                    {
                        //zero = up;
                        down.next = new List();
                        down.next.name = st;
                        down.next.points = s.nextInt();
                        down.next.next = up;
                        ll++;
                    }
                }
            }
            //в конце - вывод списка
            l = head;
            for(int i=0;i<ll;i++)
            {
                System.out.print(l.name);
                System.out.print(" ");
                System.out.println(l.points);
                l = l.next;
            }
        }
        catch(java.io.IOException e)    
        { 
            e.printStackTrace(); 
        }
    }
}
